﻿namespace Utils
{
    public static class StringExtensions
    {
        private static T ParseOrDefault<T>(this object obj, T defaultValue)
        {
            if (obj is T result)
            {
                return result;
            }

            var strValue = obj?.ToString();
            if (string.IsNullOrEmpty(strValue))
            {
                return defaultValue;
            }

            try
            {
                return (T)Convert.ChangeType(strValue, typeof(T));
            }
            catch
            {
                return defaultValue;
            }
        }

        public static bool ToBool(this object obj) => obj.ParseOrDefault(false);

        public static DateTime ToDateTime(this object obj) => obj.ParseOrDefault(DateTime.MinValue);

        public static decimal ToDecimal(this object obj) => obj.ParseOrDefault(0m);

        public static double ToDouble(this object obj) => obj.ParseOrDefault(0.0);

        public static float ToFloat(this object obj) => obj.ParseOrDefault(0f);

        public static int ToInt(this object obj) => obj.ParseOrDefault(0);

        public static long ToInt64(this object obj) => obj.ParseOrDefault(0L);

        public static int ToMinInt(this object obj, int minValue)
        {
            return Math.Max(obj.ToInt(), minValue);
        }

        public static int ToMaxInt(this object obj, int maxValue)
        {
            return Math.Min(obj.ToInt(), maxValue);
        }

        public static string ToStringExt(this object obj, string defaultValue = "")
        {
            return obj?.ToString() ?? defaultValue;
        }

        public static ushort ToUint16(this object obj) => obj.ParseOrDefault((ushort)0);

        public static bool IsNullOrEmpty(this string str) => string.IsNullOrEmpty(str);

        public static bool IsNullOrEmpty(this object obj) => obj == null || obj is string str && string.IsNullOrEmpty(str);

        public static bool IsNullOrWhiteSpace(this string str) => string.IsNullOrWhiteSpace(str);

        public static bool IsNullOrWhiteSpace(this object obj) => obj == null || obj is string str && string.IsNullOrWhiteSpace(str);

        public static bool NotNull(this string str) => str != null && !string.IsNullOrEmpty(str) && !string.IsNullOrWhiteSpace(str);

        public static bool Contains(this string str, string value, StringComparison comparisonType) => str.IndexOf(value, comparisonType) >= 0;

        public static bool Contains(this string str, char value) => str.IndexOf(value) >= 0;

        public static bool StartsWith(this string str, string value, StringComparison comparisonType) => str.StartsWith(value, comparisonType);

        public static bool EndsWith(this string str, string value, StringComparison comparisonType) => str.EndsWith(value, comparisonType);

        public static bool EqualsIgnoreCase(this string str, string value) => string.Equals(str, value, StringComparison.OrdinalIgnoreCase);

        public static bool EqualsIgnoreCase(this string str, char value) => str.Length == 1 && char.ToLower(str[0]) == char.ToLower(value);

        public static bool EqualsIgnoreCase(this char c, char value) => char.ToLower(c) == char.ToLower(value);

        public static bool EqualsIgnoreCase(this string str, string value, int startIndex, int length) => string.Compare(str, startIndex, value, 0, length, StringComparison.OrdinalIgnoreCase) == 0;

        public static bool EqualsIgnoreCase(this string str, char value, int startIndex) => str.Length > startIndex && char.ToLower(str[startIndex]) == char.ToLower(value);

        public static bool EqualsIgnoreCase(this char c, char value, int startIndex) => char.ToLower(c) == char.ToLower(value);

        public static bool EqualsIgnoreCase(this string str, string value, int startIndex, int length, StringComparison comparisonType) => string.Compare(str, startIndex, value, 0, length, comparisonType) == 0;

        public static bool EqualsIgnoreCase(this string str, char value, int startIndex, StringComparison comparisonType) => str.Length > startIndex && char.ToLower(str[startIndex]) == char.ToLower(value);

        public static bool EqualsIgnoreCase(this char c, char value, int startIndex, StringComparison comparisonType) => char.ToLower(c) == char.ToLower(value);

        public static bool EqualsIgnoreCase(this string str, string value, StringComparison comparisonType) => string.Equals(str, value, comparisonType);

        public static bool EqualsIgnoreCase(this string str, char value, StringComparison comparisonType) => str.Length == 1 && char.ToLower(str[0]) == char.ToLower(value);

        public static bool EqualsIgnoreCase(this char c, char value, StringComparison comparisonType) => char.ToLower(c) == char.ToLower(value);

        public static bool EqualsIgnoreCase(this string str, string value, int startIndex, StringComparison comparisonType) => string.Compare(str, startIndex, value, 0, value.Length, comparisonType) == 0;
    }
}